home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS26.ADF / SoundScape / LatticeExamples / vu.c < prev    next >
C/C++ Source or Header  |  1989-01-26  |  8KB  |  288 lines

  1. /*      VU.C            VU Meter for the Sampler
  2.  
  3.         (c) 1987        Todor Fay
  4.  
  5.     LATTICE C version:
  6.  
  7.     lc1 vu
  8.     lc2 -v vu
  9.     atom vu.o ram:foo -cd
  10.     copy ram:foo vu.o
  11.     blink with vu.with
  12. */
  13.  
  14. #include "exec/exec.h"
  15. #include "exec/types.h"
  16. #include "soundscape.h"
  17. #include "intuition/intuition.h"
  18.  
  19. /*      Images for the LEDs.  A red LED for lighting, 
  20.         a blue LED for turning it back off 
  21.         (the background color.)
  22. */
  23.  
  24. UWORD redleddata[] = {        /* 16 x 3 */ 
  25. 65535,        
  26. 65535,        
  27. 65535,        
  28. 65535,        
  29. 65535,        
  30. 65535,        
  31. };
  32.  
  33. struct Image redledimage = { 0,0,16,3,2,redleddata,3,0,0 };
  34.  
  35. UWORD blueleddata[] = {        /* 16 x 3 */ 
  36. 0,        
  37. 0,        
  38. 0,        
  39. 0,        
  40. 0,        
  41. 0,        
  42. };
  43.  
  44. struct Image blueledimage = { 0,0,16,3,2,blueleddata,3,0,0 };
  45.  
  46. /*      We don't need any Intuition Gadgets, just a 
  47.         window to display the LEDs in.
  48.         This was designed with Power Windows.
  49. */
  50.  
  51. struct NewWindow NewWindowStructure = {
  52.         0,0,
  53.         250,20,
  54.         0,1,
  55.         NULL,
  56.         WINDOWDRAG+WINDOWDEPTH,
  57.         NULL,
  58.         NULL,
  59.         "VU Meter",
  60.         NULL,
  61.         NULL,
  62.         5,5,
  63.         0,0,
  64.         WBENCHSCREEN
  65. };
  66.  
  67. short thisport;                     /* This port's id. */
  68. long SoundScapeBase;                /* SoundScape library. */
  69. long IntuitionBase;
  70.  
  71. /*      We need a place to store the Sampler's
  72.         output routine address, since we are replacing
  73.         the code pointer in its port structure
  74.         with our own.
  75. */
  76.  
  77. void (*sampleroutcode) ();
  78. struct Window *vuwindow;        /* Display window. */
  79.  
  80. /*      We need an array of velocity values for each
  81.         note that is being played.  These are zeroed
  82.         for no note. 
  83.         If you add up all the velocities in this 
  84.         array, you should get totalvolume, which
  85.         is used to determine the number of LEDs to
  86.         light.
  87. */
  88.  
  89. unsigned char velocity[128];        
  90. unsigned short totalvolume;
  91.  
  92. insertoutcode(note)
  93.  
  94. /*      This output routine is not given to the Patch
  95.         Panel in the AddMidiPort call.  Instead, this
  96.         routine replaces the Sampler output code, and
  97.         then calls it.  So, this is inserted there by
  98.         the open routine.
  99.  
  100.         Check the note status.  If it is NOTEON or NOTEOFF,
  101.         we want to use it for the display.
  102.  
  103.         Start by decrementing the totalvolume by 
  104.         velocity[note->value].  If this is a NOTEOFF
  105.         event, this reduces totalvolume appropriately.
  106.         If this is a NOTEON event, this clears any
  107.         previous NOTEON that was stored.  This is
  108.         neccessary because we aren't supporting multiple
  109.         playing of the same note (for simplicity.)
  110.  
  111.         If this is a NOTEON event, increment totalvolume
  112.         by the velocity of this note.  Store this
  113.         velocity in the velocity array.  
  114.  
  115.         Else, for a NOTEOFF event, simply put zero in
  116.         the velocity array - there is no note being
  117.         played.
  118.  
  119.         Compute how many LEDs should be on from 
  120.         totalvolume.  Each additional LED represents
  121.         a doubling in volume, so figure what the most
  122.         significant bit of totalvolume is.
  123.  
  124.         If the new top LED position (newvupos) is
  125.         greater than the currently displayed one
  126.         (vupos), draw in the extra LEDs.  Else,
  127.         if newvupos is less than vupos, erase 
  128.         LEDs down to newvupos.
  129.  
  130.         Finally, forward the note event to the 
  131.         Sampler by calling its output routine.
  132. */
  133.         
  134. struct Note *note;
  135.  
  136. {
  137.     unsigned char status = note->status & 0xF0;
  138.     static short vupos = 0;
  139.     short newvupos, index;
  140.     if (sampleroutcode) {
  141.         if ((status == NOTEON) || (status == NOTEOFF)) {
  142.             totalvolume -= velocity[note->value];
  143.             if ((status == NOTEON) && note->velocity) {
  144.                 totalvolume += note->velocity;
  145.                 velocity[note->value] = note->velocity;
  146.             }
  147.             else velocity[note->value] = 0;
  148.             newvupos = 0;
  149.             index = 4;
  150.             for (;index < totalvolume; index = index << 1)
  151.                  newvupos++;
  152.             if (newvupos < vupos) {
  153.                 for (;vupos > newvupos; vupos--) 
  154.                     DrawImage(vuwindow->RPort,
  155.                         &blueledimage,-10 + vupos * 20,13);
  156.             }
  157.             else if (newvupos > vupos) {
  158.                 vupos++;
  159.                 for (;vupos <= newvupos; vupos++) 
  160.                     DrawImage(vuwindow->RPort,
  161.                         &redledimage,-10 + vupos * 20,13);
  162.             }
  163.             vupos = newvupos;
  164.         }
  165.         (*sampleroutcode) (note);
  166.     }
  167.     else FreeNode(note);
  168. }
  169.  
  170. outcode(note)
  171.  
  172. /*      This, the outcode for this module, does
  173.         nothing.  
  174. */
  175.  
  176. struct Note *note;
  177.  
  178. {
  179.     FreeNode(note);
  180. }
  181.  
  182.  
  183. opencode(direction)
  184.  
  185. /*      This installs the VU meter.
  186.         
  187.         If this is to install the output routine:
  188.  
  189.         Get the Port structure for the Sampler.
  190.         If the Sampler already has its output
  191.         code stolen, (samplerport->show has somebody's
  192.         port id) do nothing.  Else, open the window,
  193.         give samplerport->outcode insertoutcode 
  194.         and put the Sampler's output code
  195.         in samplercode.  Set samplerport->show to
  196.         this port's id, so no other module will
  197.         monkey with it.
  198. */
  199.  
  200. char direction;
  201.  
  202. {
  203.     short i;
  204.     struct Port *samplerport;
  205.     if (!direction) {
  206.         samplerport = (struct Port *) 
  207.             MidiPort(FindMidiPort("sampler"));
  208.         if (samplerport) {
  209.             if (samplerport->show) {
  210.                 CloseMidiPort(samplerport->show,0);
  211.             }
  212.             if (!samplerport->show) {
  213.                 vuwindow = (struct Window *) 
  214.                     OpenWindow(&NewWindowStructure);
  215.                 if (vuwindow) {
  216.                     totalvolume = 0;
  217.                     for (i=0; i < 128; i++) 
  218.                         velocity[i] = 0;        
  219.                     sampleroutcode = samplerport->outcode;
  220.                     samplerport->outcode = insertoutcode;
  221.                     samplerport->show = thisport;
  222.                     return(1);
  223.                 }
  224.             }
  225.         }
  226.     }
  227.     return(0);
  228. }
  229.  
  230.  
  231. closecode(direction)
  232.  
  233. /*      This deactivates the VU Meter.
  234.  
  235.         Simply return the Sampler's output routine 
  236.         to its Port structure and clear 
  237.         samplerport->show.  Close the display
  238.         window.
  239. */
  240.  
  241.     struct Port *samplerport;
  242.     if (!direction) {
  243.         samplerport = (struct Port *) 
  244.             MidiPort(FindMidiPort("sampler"));
  245.         if (samplerport && sampleroutcode) {
  246.             samplerport->outcode = sampleroutcode;
  247.             samplerport->show = 0;
  248.         }
  249.         if (vuwindow) CloseWindow(vuwindow);
  250.         vuwindow = 0;
  251.     }
  252.     return(1);
  253. }
  254.  
  255. /*      The main program is standard with one addition:
  256.         After installing this port, call OpenMidiPort
  257.         to activate it.  This is needed because there
  258.         is no icon for the user to click on.  We
  259.         could have added that icon, but it would be
  260.         one more item on the Patch Panel, cluttering
  261.         it and causing some confusion since nothing
  262.         can be sent directly to it.
  263.         There is a chance OpenMidiPort will fail.  This
  264.         is because the Sampler's output routine was
  265.         already stolen.  If so, there is no need to
  266.         stick around, so call RemoveMidiPort and leave.
  267.         Normally, RemoveMidiPort is done by SoundScape
  268.         when it closes down, but this time we'll
  269.         do it ourselves to get out early.
  270. */
  271.  
  272. main() {
  273.     IntuitionBase = OpenLibrary("intuition.library",0);
  274.     SoundScapeBase = OpenLibrary("soundscape.library",0);
  275.     if (SoundScapeBase) {
  276.         CloseLibrary(SoundScapeBase);
  277.         thisport = AddMidiPort(opencode,closecode,0,
  278.             outcode,0,0,-1,"vu meter");
  279.         if (OpenMidiPort(thisport,0)) {
  280.             SetTaskPri(FindTask(0),-20);
  281.             while (MidiPort(thisport)) Delay(100);
  282.         }
  283.         else RemoveMidiPort(thisport);
  284.     }
  285.     CloseLibrary(IntuitionBase);
  286. }
  287.